/**
 *
 * @author Juan Pablo
 *
 */
public class ControladorRC {
	// atributos de clase
	private RAM memoria;
	private Cache miCache;
	private int indice;
	private Object[][] cacheVisual;
	private boolean[] actualizados;

	/**
	 * inicializa el ControladorRC
	 */
	public ControladorRC() {
		indice = 0;
		memoria = new RAM();
		miCache = new Cache(memoria);
		cacheVisual = new Object[64][5];
		actualizados = new boolean[64];
	}

	/**
	 * peticion de la cpu
	 *
	 * @param linea,
	 *            linea en la que se encuentra el dato en la memoria RAM
	 * @return
	 */
	public boolean peticion(int linea) {
		indice++;
		if (indice == 10) {
			indice = 0;
			miCache.actualizar();
		}
		if (miCache.comprobar(linea)) {
			return true;
		} else {
			int[] bloque = memoria.leerBloque(linea);
			miCache.guardarBloque(bloque, linea);
			return false;
		}
	}

	/**
	 * Escribir un dato en la memoria ram
	 *
	 * @param linea,
	 *            direccion en la que se quiere escribir;
	 * @param dato,
	 *            dato que se quiere escribir
	 */
	public void escribirEnRam(int linea, int dato) {
		if (miCache.comprobar(linea)) {
			LineaCache miLinea = miCache.getLinea(
					Utilidades.calcularTag(linea), Utilidades
							.calcularGrupo(linea));
			if (miLinea != null) {
				int[] aux = miLinea.getBloque();
				aux[ linea % 4] = dato;
				miLinea.setBloque(aux);
				memoria.escribirBloque(linea, aux);
				miLinea.setActualizado(true);
			} else {
				System.out.println("Ocurrio un error en la actualizacion");
			}
		} else {
			memoria.guardarLinea(linea, dato);
		}
	}

	/**
	 * actualiza una matriz para los componentes visuales y un arreglo que
	 * indica si el dato esta o no actualizado
	 */
	public void actualizar() {
		Object[][] aux;
		int fila = 0;
		for (int conjunto = 0; conjunto < Utilidades.NUMEROCONJUNTOS; conjunto++) {
			aux = miCache.getConjunto(conjunto).construirMatriz();
			for (int i = 0; i < Utilidades.LINEASPORCONJUNTO; i++) {
				for (int j = 0; j < Utilidades.PALABRASPORLINEA + 1; j++) {
					cacheVisual[fila][j] = aux[i][j];
				}
				fila++;
			}
		}

		boolean[] auxB;
		int x = 0;
		for (int h = 0; h < 16; h++) {
			auxB = miCache.getActualizados(h);
			for (int g = 0; g < 4; g++) {
				actualizados[x] = auxB[g];
				x++;
			}
		}
	}

	/**
	 * devuelve una matriz para los componentes visuales
	 *
	 * @return matriz de objetos con el contenido de la cache
	 */
	public Object[][] getMemoria() {
		actualizar();
		return cacheVisual;
	}

	/**
	 * obtener las posiciones atualizadas
	 *
	 * @return, arreglo de booleanos con las posiciones actualizadas
	 */
	public boolean[] getActualizados() {
		actualizar();
		return actualizados;
	}
	/**
	 * Metodo que retorna el indice en el cual va un conjunto
	 * @param conjunto, indice del conjunto
	 * @return, int con el valor del indice
	 */
	public int getIndice(int conjunto) {
		return miCache.getIndice(conjunto);
	}
	/**
	 * metodo que crea una ram de 2048 lineas
	 */
	public void crearRam(){
		memoria.crearRAM(2048);
	}
}
